﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ArmyBodger.Core;

namespace ArmyBodger.UI {
    /// <summary>
    /// The current unit's equipment
    /// </summary>
    public partial class EquipmentPanel : UserControl {
        private int lastEquipmentOptionVerticalScrollAmount = 0;

        /// <summary>
        /// Constructor
        /// </summary>
        public EquipmentPanel() {
            InitializeComponent();
        }
        /// <summary>
        /// The current entry
        /// </summary>
        protected EntryItem currentEntry = null;
        public EntryItem CurrentEntry {
            get {
                return this.currentEntry;
            }
            set {
                this.currentEntry = value;
                this.UpdatePanel();
            }
        }
        /// <summary>
        /// Update the panel contents
        /// </summary>
        public void UpdatePanel() {
            if (this.currentEntry == null) {
                this.headerPanel.Title = "No Entry";
                this.Clear();
                return;
            } else {
                this.headerPanel.Title = this.currentEntry.Entry.Name;
                this.PopulatePanel();
                this.PopulateUpgrades();
            }
        }
        /// <summary>
        /// Clear the panel contents
        /// </summary>
        public void Clear() {
            // clearing adds an annoying flash - any way to fix that?
            this.panelContents.Controls.Clear();
            this.panelUpgrades.Controls.Clear();
            this.comboBoxUnits.Items.Clear();
            this.comboBoxAddUnits.Items.Clear();
            this.comboBoxUnits.Enabled = 
                this.buttonAddUnit.Enabled = this.buttonDecrement.Enabled =
                this.buttonDelUnit.Enabled = this.buttonIncrement.Enabled =
                this.comboBoxAddUnits.Enabled = false;
        }
        protected bool updating = false;
        /// <summary>
        /// Populate the panels contents
        /// </summary>
        public void PopulatePanel() {
            this.updating = true;
           lastEquipmentOptionVerticalScrollAmount =  this.panelContents.VerticalScroll.Value; // VerticalScroll.Value;

            this.Clear(); 
            this.PopulateUnitOptions();
            this.PopulateUpgrades();
            this.comboBoxUnits.Enabled = true;
            Unit primary = null;
            List<Unit> choices = new List<Unit>();
            foreach (Unit unit in this.currentEntry.Entry.Units) {
                if (unit.IsPrimary && primary == null) {
                    primary = unit;
                }
                bool exists = false;
                foreach (Unit existing in choices) {
                    if (existing.Name == unit.Name) {
                        exists = true;
                        break;
                    }
                }
                if (!exists) {
                    choices.Add(unit);
                }
            }
            this.comboBoxUnits.Items.AddRange(choices.ToArray());
            this.updating = false;
            if (primary == null) {
                this.comboBoxUnits.SelectedIndex = 0;
            } else {
                this.comboBoxUnits.SelectedItem = primary;
            }
        }
        /// <summary>
        /// Populate the unit options buttons
        /// </summary>
        public void PopulateUnitOptions() {
            this.comboBoxAddUnits.Items.Clear();
            string primary = this.currentEntry.Entry.GetPrimary();
            if (primary.Length > 0) {
                this.labelPrimaryUnit.Text = primary;
                this.labelPrimaryUnit.ForeColor = Color.Black;
                UnitCollection units = this.currentEntry.Entry.Units.GetUnitsByName(
                    primary
                    );
                Unit template = this.currentEntry.Entry.PossibleUnits.GetUnitsByName(
                    primary)[0];
                int count = units.Count;
                foreach (Unit unit in this.currentEntry.Entry.Units) {
                    if (unit.Name != template.Name && unit.Replaces == template.Name) {
                        count++;
                    }
                }
                this.buttonIncrement.Enabled = count < template.Maximum;
                this.buttonDecrement.Enabled = count > template.Minimum;
            } else {
                this.labelPrimaryUnit.Text = "No primary unit";
                this.labelPrimaryUnit.ForeColor = Color.DarkGray;
            }
            foreach (Unit unit in this.currentEntry.Entry.PossibleUnits) {
                if (unit.Name != primary) {
                    comboBoxAddUnits.Items.Add(unit);
                }               
            }
            comboBoxAddUnits.Enabled = comboBoxAddUnits.Items.Count > 0;
            if (comboBoxAddUnits.Enabled) {
                comboBoxAddUnits.SelectedIndex = 0;
            }
        }
        /// <summary>
        /// Populate the list of Entry upgrades
        /// </summary>
        public void PopulateUpgrades() {
            int top = 0;
            this.panelUpgrades.Controls.Clear();
            foreach (Upgrade upgrade in this.currentEntry.Entry.Upgrades) {
                Label upgradeLabel = new Label();
                upgradeLabel.Text = upgrade.Name;
                upgradeLabel.Top = top;
                upgradeLabel.Height = 18;
                upgradeLabel.Anchor = AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Right;
                upgradeLabel.Left = 2;
                CheckBox cb = new CheckBox();
                cb.Tag = upgrade;
                cb.Width = 35;                
                cb.Left = this.panelUpgrades.Width - (cb.Width + 2);
                cb.Top = top;
                cb.Checked = upgrade.Applied;
                cb.Anchor = AnchorStyles.Top | AnchorStyles.Right;
                cb.CheckedChanged += new EventHandler(UpgradeCheckBoxChanged);
                upgradeLabel.Width = this.panelUpgrades.Width - (cb.Width +5);
                top += upgradeLabel.Height + 2;
                this.panelUpgrades.Controls.Add(upgradeLabel);
                this.panelUpgrades.Controls.Add(cb);
            }
            if (this.currentEntry.Entry.Upgrades.Count == 0) {
                Label message = new Label();
                message.Text = "No upgrades available for " + this.currentEntry.Entry.Name;
                message.Width = this.panelUpgrades.Width;
                message.Height = this.panelUpgrades.Height;
                message.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Bottom | AnchorStyles.Right;
                message.TextAlign = ContentAlignment.MiddleCenter;
                this.panelUpgrades.Controls.Add(message);
            }
        }
        /// <summary>
        /// Populate the list of equipment options
        /// </summary>
        /// <param name="unit">The current unit</param>
        public void PopulateEquipment(Unit unit) {
            this.updating = true;
            Point scrollPositon = new Point(0,0);
            this.panelContents.Controls.Clear();
            int top = 0;
            List<string> categories = new List<string>();
            Dictionary<string, EquipmentOptionCollection> groups = new Dictionary<string, EquipmentOptionCollection>();
            EquipmentOptionCollection fullEquipmentCollection = new EquipmentOptionCollection();

            foreach (Upgrade upgrade in this.currentEntry.Entry.Upgrades)
            {
                if (!upgrade.Applied)
                    continue;

                foreach (KeyValuePair<string, EquipmentOptionCollection> kvp in unit.Archetypes)
                {
                    if (kvp.Key == upgrade.Name)
                        fullEquipmentCollection.AddRange(kvp.Value);
                }
            }

            fullEquipmentCollection.AddRange(unit.Equipment);
            
            foreach (EquipmentOption option in fullEquipmentCollection) {
                string category = option.Equipment.Category;
                if (!String.IsNullOrEmpty(option.OverridenCategoryName)) {
                    category = option.OverridenCategoryName;
                }
                if (!categories.Contains(category)) {
                    categories.Add(category);
                    groups.Add(category, new EquipmentOptionCollection());
                }
                groups[category].Add(option);
            }
            
            foreach (string category in categories) {
                Label lc = new Label();
                lc.Left = 2;
                lc.Top = top;
                lc.Text = category;
                lc.Font = new Font(lc.Font, FontStyle.Bold);
                lc.Width = this.panelContents.ClientSize.Width;
                lc.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
                lc.Height = 18;
                this.panelContents.Controls.Add(lc);
                top += lc.Height + 2;
                foreach (EquipmentOption option in groups[category]) {
                    
                    Label l = new Label();
                    l.Top = top;
                    l.Text = option.Description;
                    l.Left = 2;
                    l.Height = 18;
                    l.Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top;
                    this.panelContents.Controls.Add(l);

                    // Draw Panel for Multi-Model Groups
                    if (this.currentEntry.Entry.Units.GetUnitsByName(unit.Name).Count > 1) {
                        NumericUpDown nud = new NumericUpDown();
                        int unitCount = this.currentEntry.Entry.Units.GetUnitsByName(unit.Name).Count;
                        if (option.Maximum == 0)
                        {
                            nud.Maximum = unit.Maximum - (unit.Maximum - unitCount);
                        }
                        else
                        {
                            nud.Maximum = option.Maximum;
                            if (nud.Maximum > unitCount)
                                nud.Maximum = unitCount;
                        }
                        nud.Name = unit.Name + "." + option.Equipment.Name + "." + "nud";
                        nud.Value = currentEntry.Entry.NumberOfUnitsEquipped(unit.Name, option.Equipment.Name);
                        nud.Top = top;
                        nud.Width = 35;
                        nud.Height = 18;
                        nud.Anchor = AnchorStyles.Top | AnchorStyles.Right;
                        nud.Left = this.panelContents.ClientSize.Width - nud.Width;
                        int id = nud.Right;
                        nud.ValueChanged += new EventHandler(OptionQuantityChanged);
                        nud.Tag = new NumericUpDownTag(unit, this.currentEntry, option, null);
                        if (option.Fixed) {
                            l.ForeColor = Color.DarkGray;
                            nud.Enabled = false;
                        }
                        if (option.Default) {
                            l.Font = new System.Drawing.Font(l.Font, FontStyle.Bold);
                        }
                        l.Width = this.panelContents.ClientSize.Width - (nud.Width + 2 + 2);
                        nud.Left = this.panelContents.ClientSize.Width - nud.Width - 2;
                        this.panelContents.Controls.Add(nud);
                        foreach (EquipmentOption replacement in option.Replacements)
                        {
                            top += l.Height + 2;
                            l = new Label();
                            l.Text = " - " + replacement.Description;
                            l.Top = top;
                            l.Left = 2;
                            l.Height = 18;
                            l.Anchor = AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Right;
                            nud = new NumericUpDown();
                            if (replacement.Maximum == 0)
                            {
                                nud.Maximum = unit.Maximum - (unit.Maximum - unitCount);
                            }
                            else
                            {
                                nud.Maximum = replacement.Maximum;
                                if (nud.Maximum > unitCount)
                                    nud.Maximum = unitCount;
                            }
                            nud.Name = unit.Name + "." + option.Equipment.Name + "." + replacement.Equipment.Name + "." + "nud";
                            int count = 0;
                            foreach (Unit u in this.currentEntry.Entry.Units.GetUnitsByName(unit.Name))
                            {
                                if (u.Equipment[option.Equipment.Name].Replacement != null && u.Equipment[option.Equipment.Name].Replacement.Equipment.Name == replacement.Equipment.Name)
                                {
                                    count++;
                                }
                            }
                            nud.Value = count;
                            nud.Top = top;
                            nud.Width = 35;
                            nud.Height = 18;
                            nud.Left = this.panelContents.ClientSize.Width - nud.Width - 2;
                            nud.Anchor = AnchorStyles.Right | AnchorStyles.Top;
                            nud.ValueChanged += new EventHandler(ReplacementQuantityChanged);
                            nud.Tag = new NumericUpDownTag(unit, this.currentEntry, option, replacement);
                            l.Width = this.panelContents.ClientSize.Width - (nud.Width + 2 + 2);
                            this.panelContents.Controls.Add(l);
                            this.panelContents.Controls.Add(nud);
                        }
                    } 
                    // Draw Panel for Single-Model Groups
                    else {
                        CheckBox cb = new CheckBox();
                        cb.Checked = option.Equipped;
                        cb.Tag = new CheckBoxTag(unit, currentEntry, option, null);
                        if (option.ReplacementApplied) {
                            cb.Checked = false;
                        }
                        if (option.Fixed) {
                            cb.Enabled = false;
                            l.ForeColor = Color.DarkGray;
                        }
                        cb.Top = top;
                        cb.Width = 35;
                        cb.Height = 18;
                        cb.Left = this.panelContents.ClientSize.Width - cb.Width;
                        cb.Anchor = AnchorStyles.Top | AnchorStyles.Right;
                        cb.CheckedChanged += new EventHandler(OptionCheckbox);
                        l.Width = this.panelContents.ClientSize.Width - (cb.Width + 2);
                        this.panelContents.Controls.Add(cb);
                        foreach (EquipmentOption replacement in option.Replacements) {
                            top += l.Height + 2;
                            l = new Label();
                            l.Text = " - " + replacement.Description;
                            l.Top = top;
                            l.Left = 2;
                            l.Height = 18;
                            l.Anchor = AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Right;
                            cb = new CheckBox();
                            cb.Top = top;
                            cb.Width = 35;
                            cb.Height = 18;
                            cb.Anchor = AnchorStyles.Right | AnchorStyles.Top;
                            cb.Tag = new CheckBoxTag(unit, this.currentEntry, option, replacement);
                            cb.CheckedChanged += new EventHandler(ReplacementCheckBox);
                            l.Width = this.panelContents.ClientSize.Width - (cb.Width + 2);
                            cb.Checked = option.Replacement == replacement;
                            this.panelContents.Controls.Add(l);
                            cb.Left = this.panelContents.ClientSize.Width - cb.Width;
                            this.panelContents.Controls.Add(cb);
                        }
                    }
                    top += l.Height + 2;

                }
            }
            if (top == 0) {
                Label label = new Label();
                label.Text = "No options for " + unit.Name;
                label.Width = this.panelContents.ClientSize.Width;
                label.Height = this.panelContents.Height;
                label.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Bottom;
                label.TextAlign = ContentAlignment.MiddleCenter;
                this.panelContents.Controls.Add(label);
            }
            this.panelContents.VerticalScroll.Value = lastEquipmentOptionVerticalScrollAmount;
            this.updating = false;
        }
        /// <summary>
        /// A subitem was checked/unchecked either set the item or reset to the toplevel one
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void ReplacementCheckBox(object sender, EventArgs e) {
            if (!this.updating) {
                CheckBox cb = sender as CheckBox;
                CheckBoxTag cbt = cb.Tag as CheckBoxTag;
                if (cb.Checked) {
                    cbt.Option.EquipReplacement(cbt.Replacement.Equipment.Name);
                    if (!String.IsNullOrEmpty(cbt.Replacement.OnEquipEvent)) {
                        dynamic b = ScriptCore.Instance.Execute(cbt.Replacement.OnEquipEvent);
                        if (b != null) {
                            try {
                                if (b == false) {
                                    cbt.Option.Reset();
                                }
                            } catch { }
                        }
                    }
                } else {
                    cbt.Option.Reset();
                }
                cbt.Entry.Refresh();
                BodgerForm.MainForm.GetListControl().UpdateTotal();                
                this.PopulateEquipment(cbt.Unit);
            }
        }
        /// <summary>
        /// The top level item was checked, reset the replacements
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void OptionCheckbox(object sender, EventArgs e) {
            if (!this.updating) {
                CheckBox cb = sender as CheckBox;
                CheckBoxTag cbt = cb.Tag as CheckBoxTag;
                dynamic b = null;
                if (cb.Checked && !String.IsNullOrEmpty(cbt.Option.OnEquipEvent)) {
                    b = ScriptCore.Instance.Execute(cbt.Option.OnEquipEvent);
                    if (b != null) {
                        try {
                            if (b == false) {
                                cbt.Option.Reset();
                            }
                        } catch {

                        }
                    }
                }
                cbt.Option.EquipReplacement("");
                if(b == null || (b is bool && b == true))
                    cbt.Option.Equipped = cb.Checked;
                // Dont allow toplevel items to be unticked manually
                if (cbt.Option.HasReplacements && cbt.Option.Replacement == null) {
                    cbt.Option.Equipped = true;
                }
                else
                    
                cbt.Entry.Refresh();
                BodgerForm.MainForm.GetListControl().UpdateTotal();
                this.PopulateEquipment(cbt.Unit);
            }
        }
        /// <summary>
        /// NumericBox event
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void OptionQuantityChanged(object sender, EventArgs e) {
            if (!this.updating) {
                NumericUpDown control = sender as NumericUpDown;
                NumericUpDownTag tag = control.Tag as NumericUpDownTag;
                int oldCount = 0;
                foreach (Unit unit in tag.Entry.Entry.Units.GetUnitsByName(tag.Unit.Name)) {
                    if (unit.Equipment[tag.Option.Equipment.Name].Equipped) {
                        oldCount++;
                    }
                }
                if (oldCount < control.Value) {
                    // Incremented
                    foreach (Unit unit in tag.Entry.Entry.Units.GetUnitsByName(tag.Unit.Name)) {
                        EquipmentOption option = unit.Equipment[tag.Option.Equipment.Name];
                        if (!option.Equipped) {
                            if (!String.IsNullOrEmpty(option.OnEquipEvent)) {
                                dynamic result = ScriptCore.Instance.Execute(option.OnEquipEvent);
                                if (result is bool && result == false)
                                {
                                    this.PopulatePanel();
                                    tag.Entry.Refresh();
                                    BodgerForm.MainForm.GetListControl().UpdateTotal();
                                    return;
                                }
                            }
                            unit.Equipment[tag.Option.Equipment.Name].Reset();
                            break;
                        }
                    }
                } else {
                    // Decremented
                    foreach (Unit unit in tag.Entry.Entry.Units.GetUnitsByName(tag.Unit.Name)) {
                        EquipmentOption option = unit.Equipment[tag.Option.Equipment.Name];
                        // Don't Decrement if you can switch it for other wargear
                        if (option.Equipped && option.Replacements.Count == 0) {
                            unit.Equipment[tag.Option.Equipment.Name].Equipped = false;
                            break;
                        }
                    }
                }
                this.PopulatePanel();
                tag.Entry.Refresh();
                BodgerForm.MainForm.GetListControl().UpdateTotal();
            }
        }

        /// <summary>
        /// NumericBox event
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void ReplacementQuantityChanged(object sender, EventArgs e)
        {
            if (!this.updating)
            {
                NumericUpDown control = sender as NumericUpDown;
                NumericUpDownTag tag = control.Tag as NumericUpDownTag;
                int oldCount = 0;
                foreach (Unit unit in tag.Entry.Entry.Units.GetUnitsByName(tag.Unit.Name))
                {
                    if (unit.Equipment[tag.Option.Equipment.Name].Replacement != null && unit.Equipment[tag.Option.Equipment.Name].Replacement.Equipment.Name == tag.Replacement.Equipment.Name)
                    {
                        oldCount++;
                    }
                }
                if (oldCount < control.Value)
                {
                    // Incremented
                    bool equipped = false;
                    foreach (Unit unit in tag.Entry.Entry.Units.GetUnitsByName(tag.Unit.Name))
                    {
                        EquipmentOption option = unit.Equipment[tag.Option.Equipment.Name];
                        EquipmentOption replacement = option.Replacements[tag.Replacement.Equipment.Name];
                        if (option.Replacement == null)
                        {
                            if (!String.IsNullOrEmpty(replacement.OnEquipEvent))
                            {
                                dynamic result = ScriptCore.Instance.Execute(replacement.OnEquipEvent);
                                if (result is bool && result == false)
                                {
                                    this.PopulatePanel();
                                    tag.Entry.Refresh();
                                    BodgerForm.MainForm.GetListControl().UpdateTotal();
                                    return;
                                }
                            }
                            option.EquipReplacement(replacement.Equipment.Name);
                            equipped = true;
                            break;
                        }
                    }

                    if (!equipped)
                    {
                        // The unit is full of replacement gear and needs to replace the replacements
                        foreach (Unit unit in tag.Entry.Entry.Units.GetUnitsByName(tag.Unit.Name))
                        {
                            EquipmentOption option = unit.Equipment[tag.Option.Equipment.Name];
                            EquipmentOption replacement = option.Replacements[tag.Replacement.Equipment.Name];
                            if (option.Replacement.Equipment.Name != replacement.Equipment.Name)
                            {
                                if (!String.IsNullOrEmpty(option.OnEquipEvent))
                                {
                                    bool result = ScriptCore.Instance.Execute(option.OnEquipEvent);
                                    if (result == false)
                                    {
                                        this.PopulatePanel();
                                        tag.Entry.Refresh();
                                        BodgerForm.MainForm.GetListControl().UpdateTotal();
                                        return;
                                    }
                                }
                                option.EquipReplacement(replacement.Equipment.Name);
                                equipped = true; 
                                break;
                            }
                        }
                    }
                }
                else
                {
                    // Decremented
                    foreach (Unit unit in tag.Entry.Entry.Units.GetUnitsByName(tag.Unit.Name))
                    {
                        EquipmentOption option = unit.Equipment[tag.Option.Equipment.Name];
                        if (option.Replacement != null && option.Replacement.Equipment.Name == tag.Replacement.Equipment.Name)
                        {
                            unit.Equipment[tag.Option.Equipment.Name].Reset();
                            break;
                        }
                    }
                }
                this.PopulatePanel();
                tag.Entry.Refresh();
                BodgerForm.MainForm.GetListControl().UpdateTotal();
            }
        }

        /// <summary>
        /// Chosen unit type changed
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void comboBoxUnits_SelectedIndexChanged(object sender, EventArgs e) {
            this.PopulateEquipment(this.comboBoxUnits.SelectedItem as Unit);
        }
        /// <summary>
        /// An upgrade checkbox was clicked
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void UpgradeCheckBoxChanged(object sender, EventArgs e) {
            CheckBox cb = sender as CheckBox;
            Upgrade upgrade = cb.Tag as Upgrade;
            bool result = true;

            if (!String.IsNullOrEmpty(upgrade.OnUpgradeEvent))
            {
                result = ScriptCore.Instance.Execute(upgrade.OnUpgradeEvent);
            }
            
            if(result == true)
                upgrade.Applied = cb.Checked;
            
            this.currentEntry.Refresh();
            BodgerForm.MainForm.GetListControl().UpdateTotal();
            this.PopulatePanel();
        }
        /// <summary>
        /// Add Unit Combobox changed
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void comboBoxAddUnits_SelectedIndexChanged(object sender, EventArgs e) {
            ComboBox cb = sender as ComboBox;
            Unit unit = cb.SelectedItem as Unit;
            this.UpdateAddRemoveButtonStatus(unit);
        }
        /// <summary>
        /// Set the status of the Add/Del unit buttons
        /// </summary>
        /// <param name="unit">The current unit</param>
        public void UpdateAddRemoveButtonStatus(Unit unit) {
            int count = this.currentEntry.Entry.Units.GetUnitsByName(unit.Name).Count;
            this.buttonAddUnit.Enabled = count < unit.Maximum;
            this.buttonDelUnit.Enabled = count > unit.Minimum;
        }
        /// <summary>
        /// Increment the Primary Unit
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonIncrement_Click(object sender, EventArgs e) {
            this.currentEntry.Entry.AddUnit(this.labelPrimaryUnit.Text);
            this.PopulateUnitOptions();
            this.currentEntry.Refresh();
            BodgerForm.MainForm.GetListControl().UpdateTotal();
        }
        /// <summary>
        /// Decrement the Primary Unit
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonDecrement_Click(object sender, EventArgs e) {
            Unit unit = this.currentEntry.Entry.PossibleUnits.GetUnitsByName(this.labelPrimaryUnit.Text)[0];
            Unit removeMe = null;
            foreach (Unit existing in this.currentEntry.Entry.Units) {
                if (existing.Name == unit.Name) {
                    removeMe = existing;
                    break;
                }
            }
            if (removeMe != null) {
                if (unit.Replaces != null && unit.Replaces.Length > 0) {
                    this.currentEntry.Entry.AddUnit(unit.Replaces);
                }
                this.currentEntry.Entry.Units.Remove(removeMe);
            }
            this.currentEntry.Refresh();
            this.PopulateUnitOptions();
            BodgerForm.MainForm.GetListControl().UpdateTotal();
        }
        /// <summary>
        /// Add an additional unit type to the list
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonAddUnit_Click(object sender, EventArgs e) {
            Unit unit = this.comboBoxAddUnits.SelectedItem as Unit;
            this.currentEntry.Entry.AddUnit(unit.Name);
            this.currentEntry.Refresh();
            this.PopulatePanel();
            this.UpdateAddRemoveButtonStatus(unit);
            BodgerForm.MainForm.GetListControl().UpdateTotal();
        }

        private void buttonDelUnit_Click(object sender, EventArgs e) {
            Unit unit = this.comboBoxAddUnits.SelectedItem as Unit;
            Unit removeMe = null;
            foreach (Unit existing in this.currentEntry.Entry.Units) {
                if (existing.Name == unit.Name) {
                    removeMe = existing;
                    break;
                }
            }
            if (removeMe != null) {
                if (unit.Replaces != null && unit.Replaces.Length > 0) {
                    this.currentEntry.Entry.AddUnit(unit.Replaces);
                }
                this.currentEntry.Entry.Units.Remove(removeMe);
            }
            this.currentEntry.Refresh();
            this.PopulatePanel();
            this.UpdateAddRemoveButtonStatus(unit);
            BodgerForm.MainForm.GetListControl().UpdateTotal();
        }
    }
    /// <summary>
    /// Attached to the NumericUpDown boxes so that events can interract
    /// </summary>
    public class NumericUpDownTag {
        /// <summary>
        /// The Unit
        /// </summary>
        public Unit Unit { get; set; }
        /// <summary>
        /// The List EntryItem
        /// </summary>
        public EntryItem Entry { get; set; }
        /// <summary>
        /// The EquipmentOption
        /// </summary>
        public EquipmentOption Option { get; set; }
        /// <summary>
        /// The EquipmentOption
        /// </summary>
        public EquipmentOption Replacement { get; set; }
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="unit">The Unit the equipment applies to</param>
        /// <param name="entry">The List EntryItem the unit belongs to</param>
        /// <param name="option">The EquipmentOption used</param>
        public NumericUpDownTag(Unit unit, EntryItem entry, EquipmentOption option, EquipmentOption replacement) {
            this.Unit = unit;
            this.Entry = entry;
            this.Option = option;
            this.Replacement = replacement;
        }
    }
    /// <summary>
    /// Attached to the CheckBoxes so that events can interact
    /// </summary>
    public class CheckBoxTag : NumericUpDownTag {
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="unit">The unit to which the checkbox applies</param>
        /// <param name="entry">The List EntryItem the unit belongs to</param>
        /// <param name="option">The toplevel EquipmentOption</param>
        /// <param name="replacment">The replacement EquipmentOption or null</param>
        public CheckBoxTag(Unit unit, EntryItem entry, EquipmentOption option, EquipmentOption replacment)
            : base(unit, entry, option, replacment) {
        }
    } 
}
